package es.duma.presentation;

import es.duma.search.SearchService;
import es.duma.search.SearchServiceHome;
import es.duma.util.config.Configurator;
import es.duma.util.log.Log;

import es.duma.util.xsl.TransformXSL;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;

import java.io.UnsupportedEncodingException;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import javax.rmi.PortableRemoteObject;

import javax.servlet.*;
import javax.servlet.http.*;

/** Servlet principal de la herramienta de busqueda
 * Recibe los parametros de busqueda y lanza la peticion contra el servicio.
 * Segun los parametros y el terminal de usuario genera una presentacion de los resultados acorde.
 */
public class Search extends HttpServlet {
   
    /**
    * Content type de la respuesta devuleta por el Servlet
    */
    //private static final String CONTENT_TYPE = "application/xhtml+xml; charset=UTF8";
    private static final String CONTENT_TYPE = "text/html; charset=UTF-8";
   
    /**
    * Cabecera del xhtml devuleto
    */
    private static final String DOC_TYPE = "<!DOCTYPE html  \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"+"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">";
    
    
    /**
     * inicializacion del servlet
     * @param config
     * @throws ServletException
     */
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }


    /**
     * Proceado de las peticiones http get contra el servlet
     * @param request peticion http
     * @param response respuesta http
     * @throws ServletException
     * @throws IOException
     */
    public void doGet(HttpServletRequest request, 
                       HttpServletResponse response) throws ServletException, IOException {
                       

        request.setCharacterEncoding("UTF-8");

        //Se fija el content-type de la respuesta
        response.setContentType(CONTENT_TYPE);
        
        //Responser
        PrintWriter out = response.getWriter();
        
        //Se obtiene el userAgent del usuario
        RequestManager.getUserAgent(request);
        
        //Se obtiene la sesion de usuario
        HttpSession sesion=RequestManager.getSession(request);
        
        //Se obtienen los parametros de la peticion
        Hashtable params=RequestManager.getParams(request);
    
         // Accion invocada
        String action="";
        if (params.get(Constants.PARAM_ACTION)!=null)
            action=(String)params.get(Constants.PARAM_ACTION);
        Log.debug(this,"Accion obtenido en la llamada "+action);
        
        
        // Posible identificador incluido en la llamada
        String id="";
        if (params.get(Constants.PARAM_ID)!=null){
            id=(String)params.get(Constants.PARAM_ID);
            Log.debug(this,"Identificador obtenido en la llamada "+id);
        }
        
        //Posible filtro de contenido
        String filter="";
        if (params.get(Constants.FILTER)!=null){
            filter=(String)params.get(Constants.FILTER);
            Log.debug(this,"Filtro de contenido "+filter);
        }
        
        //Posible filtro de ordenacion
        String order="";
        if(params.get(Constants.ORDER)!=null){
            order=(String)params.get(Constants.ORDER);
            Log.debug(this,"Los contenidos se deben ordenar por "+order);
        }
            
                    
        //Se obtiene la cadena de busqueda
        String busqueda="";
        busqueda = (String)params.get(Constants.KEY_PARAM_GET_SEARCH);
        Log.debug(this,"Peticion de busqueda recibida: "+busqueda);
        
        //Numero de contenido desde el que empezar a mostrar
        String start="1";
        if ((params.get(Constants.PARAM_START)!=null)){
            // Se comprueba que el parametro es un valor numerico aunque al xsl se pasa el valor string
            try{
                String aux=(String)params.get(Constants.PARAM_START);
                Integer.parseInt(aux);
                start=aux;
                Log.debug(this,"Se fija el comienzo 'start' del listado de contenidos en "+start);
                
            }catch (NumberFormatException e){
                Log.warn(this,"El parametro start no puede parsearse a un valor numerico. Se mantiene el valor "+start);
                
            }
            
        }
            
        
        // Marca de tiempo para controlar el tiempo total empleado
        Long ini=System.currentTimeMillis();
        
        
        // Antes de lanzar la busqueda, hay que comprobar que la busqueda no se encuentre almacenada en la sesion del usuario
        boolean newSearch=true;
        LastSearch lastSearch = (LastSearch)sesion.getAttribute(Constants.LAST_SEARCH_OBJ);
        if (lastSearch==null){
            Log.debug(this,"No hay ninguna busqueda alamacenada en la sesion del usuario");
        }else{
            Log.debug(this,"Existe una busqueda alamacenada en la sesion de usuario");
            Log.debug(this,"Se comprueba si la busqueda actual es la almacenada en la sesion de usuario");
            if (lastSearch.getKey().equals(busqueda)){
                Log.debug(this,"La busqueda esta almacenada en sesion de usuario");
                newSearch=false;
            }else{
                Log.debug(this,"La busqueda actual no coinicide con la busqueda almacenada.");
            }
            
        }

        String result="";
        if (newSearch){
            Log.debug(this,"Se inicia la nueva busqueda");
            //Se procesa la cadena de busqueda para constuir el xml
            SearchManager sm= new SearchManager(busqueda);
            String xmlSearch=sm.getXMLString();
        
            //Se efectua la busqueda
            Log.debug(this,"Se realiza la busqueda de "+xmlSearch);
            result=sm.execSearch(xmlSearch);
            Log.debug(this,"La busqueda ha concluido");
            //Log.debug(this,result);
            
            // Se almacena en la sesion del usuario la busqueda efectuada
            lastSearch =new LastSearch(busqueda,result);
            sesion.setAttribute(Constants.LAST_SEARCH_OBJ,lastSearch);
            Log.debug(this,"La busqueda ["+busqueda+"] se ha almacenado en la sesion de usuario");
        }else{
            Log.debug(this,"Se obtiene el resultado almacenado en sesion de la ultima busqueda");
            result=lastSearch.getResult();
        }
         
        // Marca de tiempo para controlar el tiempo total empleado
        Long fin=System.currentTimeMillis();
        Long time=(fin-ini);
        
        // La busqueda ha concluido. Ahora se presenta los resultados al usuario.
        
        // Si se ha incluido el parametro debug=on se envia el xml sin transformar
        if (params.containsKey(Constants.PARAM_DEBUG) && params.get(Constants.PARAM_DEBUG).equals("on")){        
            Log.debug(this,"Peticion en modo debug. Se envia el xml resultado sin transformar");
            response.setContentType("application/xml; charset=UTF8");
            out.print(result);
        }else{        
            //Se realiza la adaptacion de los resultados a la presentacion del terminal de usuario
            String xslPath=PresentationManager.getPathXSL(action,request);     
    
            
            TransformXSL xsl_transformer=new TransformXSL(xslPath);
            OutputStream output=new ByteArrayOutputStream();
            try {
                 Log.debug(this,"Se inicia la generacion de la presentacion");
                 //Obtener el xml en un InputStream
                 byte[] bytes= result.getBytes();
                 InputStream in= new ByteArrayInputStream(bytes);
                 
                 // Se anyaden los paramteros a la transformacion xsl
                 xsl_transformer.addParameter("time",time.toString());
                 xsl_transformer.addParameter("base_url",Constants.XSL_PARAM_BASE_URL);
                 xsl_transformer.addParameter("keys_search",busqueda.replace(' ','+'));
                 xsl_transformer.addParameter("action",Constants.XSL_PARAM_ACTION_DETAILS);
                 xsl_transformer.addParameter("id",id);
                 xsl_transformer.addParameter("start",start);
                 xsl_transformer.addParameter("filter",filter);
                 xsl_transformer.addParameter("order",order);
                 
                 xsl_transformer.print(in,output);
             } catch (IOException e) {
                 Log.error(this,"Error en la transformacion "+e);
             }
            
            
            //Se envia la transformacion de respuesta a la salida
            out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+output);
                   
            out.close();
        }
    }
    
    
}
